/** Essential APIs for working with ResponseConvertUtils. */
@file:JvmMultifileClass
@file:JvmName("ResponseConvertUtils")

package hos.net.soap.extension

import com.drake.net.exception.ConvertException
import com.drake.net.exception.NetException
import com.drake.net.reflect.typeTokenOf
import com.drake.net.request.converter
import hos.net.http.reflect.TypeUtil
import okhttp3.Response
import java.io.IOException
import java.lang.reflect.Type
import kotlin.coroutines.cancellation.CancellationException


/**
 * <p>Title: ResponseExtension </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2024-04-09 14:23
 * @version : 1.0
 */
/**
 * 响应体使用转换器处理数据
 * 本方法仅为兼容Java使用存在
 * @param rawType
 * @param typeArguments
 */
@Suppress("UNCHECKED_CAST")
@Throws(IOException::class)
fun <R> Response.convert(rawType: Type, vararg typeArguments: Type): R {
    try {
        if (typeArguments.isEmpty()) {
            return request.converter().onConvert<R>(rawType, this) as R
        }
        val type = TypeUtil.typeOf(rawType, *typeArguments)
        return request.converter().onConvert<R>(type, this) as R
    } catch (e: CancellationException) {
        throw e
    } catch (e: NetException) {
        throw e
    } catch (e: Throwable) {
        throw ConvertException(
            this,
            message = "An unexpected error occurred in the converter",
            cause = e
        )
    }
}

/**
 * 执行同步请求
 * @return 一个包含请求成功和错误的Result
 */
@Suppress("UNCHECKED_CAST")
fun <R> Response.toResult(rawType: Type, vararg typeArguments: Type): Result<R> {
    return try {
        if (typeArguments.isEmpty()) {
            val value = request.converter().onConvert<R>(rawType, this) as R
            return Result.success(value);
        }
        val type = TypeUtil.typeOf(rawType, *typeArguments)
        val value = request.converter().onConvert<R>(type, this) as R
        Result.success(value)
    } catch (e: Throwable) {
        Result.failure(e)
    }
}

/**
 * 响应体使用转换器处理数据
 * 本方法仅为兼容Java使用存在
 * @param type 如果存在泛型嵌套要求使用[typeTokenOf]获取, 否则泛型会被擦除导致无法解析
 */
@Suppress("UNCHECKED_CAST")
@Throws(IOException::class)
fun <R> Response.toResult(type: Type): Result<R> {
    return try {
        val value = request.converter().onConvert<R>(type, this) as R
        Result.success(value)
    } catch (e: Throwable) {
        Result.failure(e)
    }
}

/**
 * 响应体使用转换器处理数据
 */
@Throws(IOException::class)
inline fun <reified R> Response.toResult(): Result<R> {
    return try {
        val value = request.converter().onConvert<R>(typeTokenOf<R>(), this) as R
        Result.success(value)
    } catch (e: Throwable) {
        Result.failure(e)
    }
}
